﻿//-----------------------------------------------------------------------------------------------------------
// WBFSSync Project by Omega Frost 
// http://wbfssync.codeplex.com/
//
// WBFSSync is Licensed under the terms of the 
// Microsoft Reciprocal License (Ms-RL)
//-----------------------------------------------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;

namespace WbfsSync.Core
{
    //-------------------------------------------------------------------------------------------------------
    //
    //-------------------------------------------------------------------------------------------------------
    static class Native
    {
        //---------------------------------------------------------------------------------------------------
        // Native constants
        //---------------------------------------------------------------------------------------------------

        public const uint RT_STRING = 0x00000006;
        public const uint RT_ICON = 0x00000003;
        public const uint RT_GROUP_ICON = 0x0000000E;

        public const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;

        public const ushort SUBLANG_DEFAULT = 0x01;
        public const ushort LANG_NEUTRAL = 0x00;
        public const ushort LANGID = ((((ushort)(SUBLANG_DEFAULT)) << 10) | (ushort)(LANG_NEUTRAL));


        public const int WM_DEVICECHANGE = 537;

        public const int DBT_DEVICEARRIVAL = 32768;
        public const int DBT_DEVICEQUERYREMOVE = 32769;
        public const int DBT_DEVICEREMOVECOMPLETE = 32772;

        public const uint DBT_DEVTYP_VOLUME = 0x2;


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public struct DEV_BROADCAST_HDR
        {
            public uint dbch_size;
            public uint dbch_devicetype;
            public uint dbch_reserved;


            public Boolean IsVolume 
            { 
                get { return this.dbch_devicetype == DBT_DEVTYP_VOLUME; }
            }


            public DEV_BROADCAST_HDR(uint dbch_size, uint dbch_devicetype, uint dbch_reserved)
            {
                this.dbch_size = dbch_size;
                this.dbch_devicetype = dbch_devicetype;
                this.dbch_reserved = dbch_reserved;
            }
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public struct DEV_BROADCAST_VOLUME
        {
            public uint dbcv_size;
            public uint dbcv_devicetype;
            public uint dbcv_reserved;

            public uint dbcv_unitmask;
            public ushort dbcv_flags;

            public DEV_BROADCAST_VOLUME(uint dbcv_size, uint dbcv_devicetype,
                uint dbcv_reserved, uint dbcv_unitmask, ushort dbcv_flags)
            {
                this.dbcv_size = dbcv_size;
                this.dbcv_devicetype = dbcv_devicetype;
                this.dbcv_reserved = dbcv_reserved;
                this.dbcv_unitmask = dbcv_unitmask;
                this.dbcv_flags = dbcv_flags;
            }
        }


        //---------------------------------------------------------------------------------------------------
        // Native delegates
        //---------------------------------------------------------------------------------------------------

        public delegate bool EnumResNameDelegate(IntPtr hModule,
            IntPtr lpszType, IntPtr lpszName, Object lParam);


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public static Boolean IsDeviceEvent(int msg, long wParam)
        {
            return (msg == WM_DEVICECHANGE) && ((wParam == DBT_DEVICEARRIVAL) 
                || (wParam == DBT_DEVICEREMOVECOMPLETE));
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public static Boolean IsRemovingDevice(long wParam)
        {
            return wParam == DBT_DEVICEQUERYREMOVE;
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public static Boolean HasRemovedDevice(long wParam)
        {
            return wParam == DBT_DEVICEREMOVECOMPLETE;
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public static Boolean IsInsertingDevice(long wParam)
        {
            return wParam == DBT_DEVICEARRIVAL;
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public static Boolean GetDeviceBroadcast(IntPtr lParam, out DEV_BROADCAST_HDR device)
        {
            try
            {
                device = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(
                    lParam, typeof(DEV_BROADCAST_HDR));
                return true;
            }
            catch
            {
                device = new DEV_BROADCAST_HDR();
                return false;
            }
        }


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        public static Boolean GetVolumeBroadcast(IntPtr lParam, out DEV_BROADCAST_VOLUME volume)
        {
            try
            {
                volume = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(
                    lParam, typeof(DEV_BROADCAST_VOLUME));
                return true;
            }
            catch
            {
                volume = new DEV_BROADCAST_VOLUME();
                return false;
            }
        }


        //---------------------------------------------------------------------------------------------------
        // Native routines
        //---------------------------------------------------------------------------------------------------


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DeleteFile(string lpFileName);


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        [DllImport("kernel32.dll")]
        public static extern bool RemoveDirectory(string lpPathName);


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr LoadLibraryEx(String lpFileName, IntPtr hFile, uint dwFlags);


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool FreeLibrary(IntPtr hModule);


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);

        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr LockResource(IntPtr hResData);


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr FindResourceEx(IntPtr hModule, IntPtr lpType, IntPtr lpName, ushort wLanguage);


        //---------------------------------------------------------------------------------------------------
        //
        //---------------------------------------------------------------------------------------------------
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool EnumResourceNames(IntPtr hModule, IntPtr lpszType,
            EnumResNameDelegate lpEnumFunc, Object lParam);


        //------------------------------------------------------------------------------------------
        // Returns a message from an error code
        //------------------------------------------------------------------------------------------
        [DllImport("Kernel32.dll", SetLastError = true)]
        public static extern uint FormatMessage(uint dwFlags, IntPtr lpSource,
            uint dwMessageId, uint dwLanguageId, ref IntPtr lpBuffer,
            uint nSize, IntPtr pArguments);


        //------------------------------------------------------------------------------------------
        // Frees the specified local memory object
        //------------------------------------------------------------------------------------------
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr LocalFree(IntPtr hMem);
    }
}
